import sugar from '../tools/sugar'
import errorCatch from '../tools/errorCatch';
// 引入控制路由结构的方法
import controRoute from './controRoute';
import controConfig from '../../init/controConfig';
import Middleware from '../middleware/middleware';
import path from "path"
import RequestType from '../../model/RequestType';

class Route{
    static createRoute(){return new Route(sugar.super_path(2,true))}
    // 唯一身份
    private ID:string = undefined;
    // 文件信息
    private RouteData:{
        middleware:Array<any>,
        prefix:string
    } = {
        middleware:[],
        prefix:"",

    };

    static midd(arr:Array<any>,arr2:Array<any>){arr.push(...arr2,arr.pop())}

    // 构造方法,统一命名空间
    constructor(id:any=undefined){
        try{
            if(!id){id = sugar.super_path(2,true);console.log("构造参数为空,建议添加 __filename")}
            if(typeof id === 'string'){
                //获取配置中的路由文件配置
                let config = controConfig.getrouteConfig();
                //遍历
                for(let key in config){
                    let filepath = sugar.path(config[key].path);
                    if(path.join(filepath).startsWith(path.join(id))){
                        this.ID = path.join(id) ;
                        //吻合了,自动加载配置
                        this.RouteData={
                            //前缀
                            prefix: config[key].prefix==='/' ? "" : config[key].prefix,
                            //中间件  
                            middleware: controRoute.getGlobalMiddleware().concat(config[key].middleware),
                        };
                        // 初始化一下数据
                        controRoute.addUnStaticRoute(this.ID, new RequestType());
                        controRoute.addUnDynamicRoute(this.ID, new RequestType());
                        return this;
                    }
                }
                //遍历完也没有找到配置,直接报错
                console.log("报异常");
                throw new Error("并未在配置文件中找到该路由的配置,请检查配置文件");
            }else if(typeof id === 'object'){
                this.ID = path.join(id.id);
                //执行到这里,说明发来的是配置信息
                this.RouteData = {
                    prefix:id.prefix==='/' ? "" : id.prefix || "",
                    middleware:controConfig.getGlobal_Middleware().concat(id.middleware || [])
                }
            }
            // 初始化一下数据
            controRoute.addUnStaticRoute(this.ID,new RequestType());
            controRoute.addUnDynamicRoute(this.ID,new RequestType());
        }catch(err){
            errorCatch(err,"Route-57")
        }
    }

    // 重新配置这个路由实列的信息
    config(data:any){
        this.RouteData = {
            prefix:data.prefix === '/' ? "" : data.prefix,
            middleware:controConfig.getGlobal_Middleware().concat(data.middleware)
        }
    }

    // 特殊接口的配置
    private special(name:string,module:any){
        controRoute.addSpecialRoute(name,{
            modules:[],
            controller:Route.createController(name,module,name)
        });
        return { midd:(...data)=>{Route.midd(controRoute.getSpecialRoute(name).modules as Array<any>,data)}}
    }
    private createSpecial(name:string):Function{
        return (module:any)=>{
            this.special(name,module);
        }
    }

    // 特殊接口
    public $500 = this.createSpecial("500")
    public $404 = this.createSpecial("404")
    public $public = this.createSpecial("public")
    public $requestRecord = this.createSpecial("requestRecord")
    public $requestParse = this.createSpecial("requestParse")

    //执行分组
    public group({prefix="",midd=[]}:{prefix:string,midd:any},fun:Function){
        try{
            let middleware            =  this.RouteData.middleware;
            let _prefix               =  this.RouteData.prefix;
            //解析出来的组级中间件是一个Promise
            this.RouteData.middleware =  this.RouteData.middleware.concat(midd);
            this.RouteData.prefix     += prefix.startsWith("/")?prefix:"/"+prefix;
            fun();
            this.RouteData.middleware =  middleware;
            this.RouteData.prefix     =  _prefix;
        }catch(err){
            errorCatch(err,'Route:82');
        }
    }
    private createMethod(method:string){
        return (url:string,fun:any,methodName?:string)=>{
            if(url===undefined) throw new Error("url is null");
            return this.createRouteInter(method,url,Route.createController(url,fun,methodName));
        }
    }
    //any请求
    any = this.createMethod("any");
    // get请求
    get = this.createMethod("get");
    // post请求
    post = this.createMethod("post");
    // delete请求
    delete = this.createMethod("delete");
    // put请求
    put = this.createMethod("put");


    //创建路由接口
    private createRouteInter(type:string,url:string,controller:controllerStructure):middObject{
        if(!type || !url || !controller) throw new Error("参数错误")

        //处理url
        url.startsWith("/") || (url = "/"+url);
        //生成完整的url
        url = this.RouteData.prefix+url;
        //处理url
        url.startsWith("/") || (url = "/"+url);

        // 解析中间件
        let MiddlewareArr:Array<controllerStructure> = Middleware.auto_pars(this.ID, this.RouteData.middleware);

        //判断是否是有路由参数的路由
        if(Route.isParameter(url)){
            // 生成正则
            let andRout = Route.createRouteRegular(url);
            controller.parameter = andRout.parameter;

            //这是一个路由参数，生成正则表达式
            controRoute.addUnDynamicRouteInter(this.ID,type,url,{
                // 基本信息
                data:{id:this.ID,type,url,...andRout},
                // 中间件模块
                modules:MiddlewareArr,
                // 控制器模块
                controller:controller
            })
            return{
                app:this,
                midd(...data:any[]) :void{
                    let route = controRoute.getUnDynamicRouteInter(this.app.ID,type,url);
                    route.modules.push(...Middleware.auto_pars(this.app.ID, data))
                }
            }
        }else{
            controRoute.addUnStaticRouteInter(this.ID,type,url,{
                data:{id:this.ID,type,url},
                modules:MiddlewareArr,
                controller:controller
            })
        }


        //调用中间件
        return{
            app:this,
            midd(...data:any[]) :void{
                let route = controRoute.getUnStaticRouteInter(this.app.ID,type,url);
                route.modules.push(...Middleware.auto_pars(this.app.ID, data))
            }
        }
    }


    //判断是否带有路由参数
    private static isParameter(str:string):any{
        return /\/:[^/]*/g.test(str);
    }

    //创建路由正则 
    private static createRouteRegular(str:any):dynamicRouteRegular{
        let parameter = str.match(/\/:[^/]*/g).map((a:string) =>a.substring(2));
        //替换字
        let replace = str.split(/\/:[^/]*/g).filter((res:string)=>res);
        //转换关键字
        str = str.replace(/\//g,"<_GEM_>");
        //生成正则表达式
        let regular =new RegExp("^"+str.replace(/(:((?!<_GEM_>).)+)/g,`((?!<_GEM_>).)+`)+"$");
        return{
            parameter,
            replace,
            regular
        }
    }

    //解析方法 创建控制器
    private static createController(id:string,module:any,name?:string):controllerStructure{
        if(typeof module === 'string'){
            // 不是绝对路径或相对路径的话，哪就是语法糖
            let [filePath,methodName] = module.split("@");
            if(!/^[./\\]|^[A-Z]\:/.test(module)){
                filePath = sugar.path((controConfig.getAddress("controller") || "") + "/" + filePath + ".js");
                return Middleware.pars_string_middleware(filePath,methodName || name || "main",[])
            }else{
                // 解析路径
                filePath = sugar.path(filePath,{superNumber:4});
                return Middleware.pars_string_middleware(filePath,methodName || name || "main",[]);
            }
        }else{
            return Middleware.auto_pars(id,module,name);
        }
    }
}

export default Route
if(module) module.exports = Route;